/*      */ package com.zimbra.cs.db;
/*      */ 
/*      */ import com.zimbra.common.localconfig.DebugConfig;
/*      */ import com.zimbra.common.localconfig.KnownKey;
/*      */ import com.zimbra.common.localconfig.LC;
/*      */ import com.zimbra.common.service.ServiceException;
/*      */ import com.zimbra.common.util.ByteUtil;
/*      */ import com.zimbra.common.util.Log;
/*      */ import com.zimbra.common.util.StringUtil;
/*      */ import com.zimbra.common.util.ZimbraLog;
/*      */ import com.zimbra.cs.mailbox.MailServiceException;
/*      */ import com.zimbra.cs.mailbox.Mailbox;
/*      */ import com.zimbra.cs.mailbox.Mailbox.MailboxData;
/*      */ import com.zimbra.cs.mailbox.MailboxLock;
/*      */ import com.zimbra.cs.mailbox.MailboxManager;
/*      */ import com.zimbra.cs.mailbox.MailboxVersion;
/*      */ import com.zimbra.cs.mailbox.Metadata;
/*      */ import com.zimbra.cs.util.Zimbra;
/*      */ import java.io.File;
/*      */ import java.io.IOException;
/*      */ import java.io.StringReader;
/*      */ import java.sql.PreparedStatement;
/*      */ import java.sql.ResultSet;
/*      */ import java.sql.SQLException;
/*      */ import java.util.ArrayList;
/*      */ import java.util.Collection;
/*      */ import java.util.Collections;
/*      */ import java.util.HashMap;
/*      */ import java.util.HashSet;
/*      */ import java.util.Iterator;
/*      */ import java.util.List;
/*      */ import java.util.Map;
/*      */ import java.util.Set;
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ public final class DbMailbox
/*      */ {
/*      */   public static final int CI_ID;
/*      */   public static final int CI_GROUP_ID;
/*      */   public static final int CI_ACCOUNT_ID;
/*      */   public static final int CI_INDEX_VOLUME_ID;
/*      */   public static final int CI_ITEM_ID_CHECKPOINT;
/*      */   public static final int CI_CONTACT_COUNT;
/*      */   public static final int CI_SIZE_CHECKPOINT;
/*      */   public static final int CI_CHANGE_CHECKPOINT;
/*      */   public static final int CI_TRACKING_SYNC;
/*      */   public static final int CI_TRACKING_IMAP;
/*      */   public static final int CI_LAST_BACKUP_AT;
/*      */   public static final int CI_COMMENT;
/*      */   public static final int CI_LAST_SOAP_ACCESS;
/*      */   public static final int CI_NEW_MESSAGES;
/*      */   public static final int CI_INDEX_DEFERRED;
/*      */   public static final int CI_HIGHEST_INDEXED;
/*      */   public static final int CI_VERSION;
/*      */   public static final int CI_LAST_PURGE_AT;
/*      */   public static final int CI_METADATA_MAILBOX_ID = 1;
/*      */   public static final int CI_METADATA_SECTION = 2;
/*      */   public static final int CI_METADATA_METADATA = 3;
/*      */   public static final int CI_SCHEDULED_TASK_MAILBOX_ID = 3;
/*      */   public static final int CI_OUT_OF_OFFICE_MAILBOX_ID = 1;
/*      */   public static final int CI_MOBILE_DEVICES_MAILBOX_ID = 1;
/*      */   public static final int CI_PENDING_ACL_PUSH_MAILBOX_ID = 1;
/*      */   static final String DB_PREFIX_MAILBOX_GROUP = "mboxgroup";
/*      */   static final String TABLE_MAILBOX = "mailbox";
/*      */   static final String TABLE_METADATA = "mailbox_metadata";
/*      */   static final String TABLE_OUT_OF_OFFICE = "out_of_office";
/*      */   private static int MAX_COMMENT_LENGTH;
/*      */   private static final HashSet<DbTableCallback> callbacks;
/*      */   static final List<String> sTables;
/*      */   
/*      */   public static class MailboxIdentifier
/*      */   {
/*      */     public final int id;
/*      */     public final int groupId;
/*      */     
/*      */     public MailboxIdentifier(int mbox_id, int group_id)
/*      */     {
/*  118 */       this.id = mbox_id;
/*  119 */       this.groupId = group_id;
/*      */     }
/*      */     
/*      */     public String toString()
/*      */     {
/*  124 */       return "[mailbox " + this.id + ", group " + this.groupId + "]";
/*      */     }
/*      */     
/*      */     public boolean equals(Object obj)
/*      */     {
/*  129 */       if (obj == this)
/*  130 */         return true;
/*  131 */       if ((obj instanceof Number))
/*  132 */         return ((Number)obj).intValue() == this.id;
/*  133 */       if ((obj instanceof MailboxIdentifier)) {
/*  134 */         return ((MailboxIdentifier)obj).id == this.id;
/*      */       }
/*  136 */       return false;
/*      */     }
/*      */     
/*      */ 
/*      */     public int hashCode()
/*      */     {
/*  142 */       return this.id;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static void addCreateDatabaseCallback(DbTableCallback callback)
/*      */   {
/*  152 */     callbacks.add(callback);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static synchronized MailboxIdentifier getNextMailboxId(DbPool.DbConnection conn, int mailboxId)
/*      */     throws ServiceException
/*      */   {
/*  164 */     boolean explicitId = mailboxId != -1;
/*  165 */     ZimbraLog.mailbox.debug("Getting next mailbox id.  requested mailboxId=%d.", new Object[] { Integer.valueOf(mailboxId) });
/*      */     
/*  167 */     PreparedStatement stmt = null;
/*  168 */     ResultSet rs = null;
/*      */     try {
/*  170 */       if (explicitId) {
/*  171 */         stmt = conn.prepareStatement("UPDATE current_volumes SET next_mailbox_id = ? WHERE next_mailbox_id <= ?");
/*      */         
/*  173 */         stmt.setInt(1, mailboxId + 1);
/*  174 */         stmt.setInt(2, mailboxId);
/*  175 */         stmt.executeUpdate();
/*      */       }
/*      */       else
/*      */       {
/*  179 */         stmt = conn.prepareStatement("UPDATE current_volumes SET next_mailbox_id = next_mailbox_id + 1");
/*      */         
/*  181 */         stmt.executeUpdate();
/*  182 */         stmt.close();
/*  183 */         stmt = null;
/*      */         
/*  185 */         stmt = conn.prepareStatement("SELECT next_mailbox_id - 1 FROM current_volumes");
/*  186 */         rs = stmt.executeQuery();
/*  187 */         if (rs.next()) {
/*  188 */           mailboxId = rs.getInt(1);
/*      */         } else {
/*  190 */           throw ServiceException.FAILURE("Unable to assign next new mailbox id", null);
/*      */         }
/*      */       }
/*      */       
/*  194 */       MailboxIdentifier newId = new MailboxIdentifier(mailboxId, calculateMailboxGroupId(mailboxId));
/*  195 */       ZimbraLog.mailbox.debug("Returning mailboxId=%d, groupId=%d.", new Object[] { Integer.valueOf(newId.id), Integer.valueOf(newId.groupId) });
/*  196 */       return newId;
/*      */     } catch (SQLException e) {
/*  198 */       throw ServiceException.FAILURE("getting next mailbox id, mailboxId=" + mailboxId, e);
/*      */     } finally {
/*  200 */       DbPool.closeResults(rs);
/*  201 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static synchronized Mailbox.MailboxData createMailbox(DbPool.DbConnection conn, int requestedMailboxId, String accountId, String comment, int lastBackupAt)
/*      */     throws ServiceException
/*      */   {
/*  208 */     String limitClause = Db.supports(Db.Capability.LIMIT_CLAUSE) ? " ORDER BY index_volume_id " + Db.getInstance().limit(1) : "";
/*      */     
/*      */ 
/*  211 */     MailboxIdentifier newMboxId = getNextMailboxId(conn, requestedMailboxId);
/*  212 */     int mailboxId = newMboxId.id;
/*  213 */     int groupId = newMboxId.groupId;
/*      */     
/*      */ 
/*  216 */     createMailboxDatabase(conn, mailboxId, groupId);
/*      */     
/*  218 */     if ((comment != null) && (comment.length() > MAX_COMMENT_LENGTH)) {
/*  219 */       comment = comment.substring(0, MAX_COMMENT_LENGTH);
/*      */     }
/*  221 */     if (comment != null) {
/*  222 */       removeFromDeletedAccount(conn, comment);
/*      */     }
/*      */     
/*  225 */     PreparedStatement stmt = null;
/*  226 */     ResultSet rs = null;
/*      */     try
/*      */     {
/*  229 */       stmt = conn.prepareStatement("SELECT index_volume_id FROM current_volumes" + limitClause);
/*  230 */       rs = stmt.executeQuery();
/*  231 */       if (!rs.next()) {
/*  232 */         throw ServiceException.FAILURE("cannot create mailbox: no rows in database table ZIMBRA.CURRENT_VOLUME", null);
/*      */       }
/*  234 */       short indexVolume = rs.getShort(1);
/*  235 */       if (rs.next()) {
/*  236 */         ZimbraLog.mbxmgr.warn("bad state: too many rows in database table ZIMBRA.CURRENT_VOLUME");
/*      */       }
/*  238 */       rs.close();
/*  239 */       rs = null;
/*  240 */       stmt.close();
/*  241 */       stmt = null;
/*      */       
/*  243 */       if (DebugConfig.disableMailboxGroups) {
/*  244 */         Db.getInstance().registerDatabaseInterest(conn, getDatabaseName(groupId));
/*      */         
/*  246 */         if (!DebugConfig.externalMailboxDirectory)
/*      */         {
/*  248 */           stmt = conn.prepareStatement("INSERT INTO mailbox (account_id, id, last_backup_at, comment) VALUES (?, ?, ?, ?)");
/*      */           
/*  250 */           stmt.setString(1, accountId.toLowerCase());
/*  251 */           stmt.setInt(2, mailboxId);
/*  252 */           if (lastBackupAt >= 0) {
/*  253 */             stmt.setInt(3, lastBackupAt);
/*      */           } else {
/*  255 */             stmt.setNull(3, 4);
/*      */           }
/*  257 */           stmt.setString(4, comment);
/*  258 */           stmt.executeUpdate();
/*  259 */           stmt.close();
/*  260 */           stmt = null;
/*      */         }
/*      */         
/*      */ 
/*  264 */         stmt = conn.prepareStatement("INSERT INTO " + qualifyTableName(groupId, "mailbox") + "(id, account_id, index_volume_id, item_id_checkpoint, version)" + " VALUES (?, ?, ?, " + 255 + ", ?)");
/*      */         
/*      */ 
/*  267 */         stmt.setInt(1, mailboxId);
/*  268 */         stmt.setString(2, accountId.toLowerCase());
/*  269 */         stmt.setShort(3, indexVolume);
/*  270 */         stmt.setString(4, MailboxVersion.getCurrent().toString());
/*  271 */         stmt.executeUpdate();
/*      */       }
/*      */       else {
/*  274 */         stmt = conn.prepareStatement("INSERT INTO mailbox(account_id, id, group_id, index_volume_id, item_id_checkpoint, last_backup_at, comment, version) VALUES (?, ?, ?, ?, 255, ?, ?, ?)");
/*      */         
/*      */ 
/*  277 */         stmt.setString(1, accountId.toLowerCase());
/*  278 */         stmt.setInt(2, mailboxId);
/*  279 */         stmt.setInt(3, groupId);
/*  280 */         stmt.setInt(4, indexVolume);
/*  281 */         if (lastBackupAt >= 0) {
/*  282 */           stmt.setInt(5, lastBackupAt);
/*      */         } else {
/*  284 */           stmt.setNull(5, 4);
/*      */         }
/*  286 */         stmt.setString(6, comment);
/*  287 */         stmt.setString(7, MailboxVersion.getCurrent().toString());
/*  288 */         stmt.executeUpdate();
/*      */       }
/*      */       
/*  291 */       Mailbox.MailboxData data = new Mailbox.MailboxData();
/*  292 */       data.accountId = accountId;
/*  293 */       data.id = mailboxId;
/*  294 */       data.lastItemId = 255;
/*  295 */       data.schemaGroupId = groupId;
/*  296 */       data.indexVolumeId = indexVolume;
/*  297 */       data.version = MailboxVersion.getCurrent();
/*  298 */       return data;
/*      */     } catch (SQLException e) {
/*  300 */       if (Db.errorMatches(e, Db.Error.DUPLICATE_ROW)) {
/*  301 */         throw MailServiceException.ALREADY_EXISTS(accountId, e);
/*      */       }
/*  303 */       throw ServiceException.FAILURE("writing new mailbox row for account " + accountId, e);
/*      */     }
/*      */     finally {
/*  306 */       DbPool.closeResults(rs);
/*  307 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public static void createMailboxDatabase(DbPool.DbConnection conn, int mailboxId, int groupId)
/*      */     throws ServiceException
/*      */   {
/*  316 */     ZimbraLog.mailbox.debug("createMailboxDatabase(" + mailboxId + ")");
/*      */     
/*  318 */     File file = new File(LC.mailboxd_directory.value() + "/../db/create_database.sql");
/*      */     
/*  320 */     boolean succeeded = false;
/*  321 */     PreparedStatement stmt = null;
/*      */     try {
/*  323 */       String dbname = getDatabaseName(groupId);
/*  324 */       Iterator i$; DbTableCallback callback; if (Db.getInstance().databaseExists(conn, dbname))
/*      */       {
/*      */ 
/*      */ 
/*  328 */         conn.commit();
/*      */       }
/*      */       else
/*      */       {
/*  332 */         Db.getInstance().precreateDatabase(dbname);
/*      */         
/*      */ 
/*  335 */         ZimbraLog.mailbox.info("Creating database " + dbname);
/*  336 */         Db.getInstance().registerDatabaseInterest(conn, dbname);
/*      */         
/*  338 */         String template = new String(ByteUtil.getContent(file));
/*  339 */         Map<String, String> vars = new HashMap();
/*  340 */         vars.put("DATABASE_NAME", dbname);
/*  341 */         String script = StringUtil.fillTemplate(template, vars);
/*      */         
/*  343 */         DbUtil.executeScript(conn, new StringReader(script));
/*  344 */         succeeded = true; } } catch (IOException e) { Iterator i$;
/*      */       DbTableCallback callback;
/*  346 */       throw ServiceException.FAILURE("unable to read SQL statements from " + file.getPath(), e);
/*      */     } catch (SQLException e) {
/*  348 */       throw ServiceException.FAILURE("createMailboxDatabase(" + mailboxId + ")", e);
/*      */     } finally {
/*  350 */       DbPool.closeStatement(stmt);
/*  351 */       if (succeeded) {
/*  352 */         for (DbTableCallback callback : callbacks) {
/*  353 */           callback.create(conn, mailboxId, groupId);
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   static
/*      */   {
/*   74 */     int pos = 1;
/*      */     
/*      */ 
/*   77 */     CI_ID = pos++;
/*   78 */     CI_GROUP_ID = pos++;
/*   79 */     CI_ACCOUNT_ID = pos++;
/*   80 */     CI_INDEX_VOLUME_ID = pos++;
/*   81 */     CI_ITEM_ID_CHECKPOINT = pos++;
/*   82 */     CI_CONTACT_COUNT = pos++;
/*   83 */     CI_SIZE_CHECKPOINT = pos++;
/*   84 */     CI_CHANGE_CHECKPOINT = pos++;
/*   85 */     CI_TRACKING_SYNC = pos++;
/*   86 */     CI_TRACKING_IMAP = pos++;
/*   87 */     CI_LAST_BACKUP_AT = pos++;
/*   88 */     CI_COMMENT = pos++;
/*   89 */     CI_LAST_SOAP_ACCESS = pos++;
/*   90 */     CI_NEW_MESSAGES = pos++;
/*   91 */     CI_INDEX_DEFERRED = pos++;
/*   92 */     CI_HIGHEST_INDEXED = pos++;
/*   93 */     CI_VERSION = pos++;
/*   94 */     CI_LAST_PURGE_AT = pos++;
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  111 */     MAX_COMMENT_LENGTH = 255;
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  155 */     callbacks = new HashSet();
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  361 */     sTables = new ArrayList();
/*      */     
/*  363 */     if (DebugConfig.disableMailboxGroups) {
/*  364 */       sTables.add("mailbox");
/*  365 */       sTables.add("mailbox_metadata");
/*  366 */       sTables.add("out_of_office");
/*      */     }
/*  368 */     sTables.add("mail_item");
/*  369 */     sTables.add("mail_item_dumpster");
/*  370 */     sTables.add("revision");
/*  371 */     sTables.add("revision_dumpster");
/*  372 */     sTables.add("tag");
/*  373 */     sTables.add("tagged_item");
/*  374 */     sTables.add("open_conversation");
/*  375 */     sTables.add("appointment");
/*  376 */     sTables.add("appointment_dumpster");
/*  377 */     sTables.add("tombstone");
/*  378 */     sTables.add("pop3_message");
/*  379 */     sTables.add("imap_folder");
/*  380 */     sTables.add("imap_message");
/*  381 */     sTables.add("data_source_item");
/*      */   }
/*      */   
/*      */   private static void dropMailboxFromGroup(DbPool.DbConnection conn, Mailbox mbox) throws ServiceException
/*      */   {
/*  386 */     int mailboxId = mbox.getId();
/*  387 */     ZimbraLog.mailbox.info("clearing contents of mailbox " + mailboxId + ", group " + mbox.getSchemaGroupId());
/*      */     
/*  389 */     if ((DebugConfig.disableMailboxGroups) && (Db.supports(Db.Capability.FILE_PER_DATABASE))) {
/*  390 */       Db.getInstance().deleteDatabaseFile(conn, getDatabaseName(mbox));
/*  391 */       return;
/*      */     }
/*      */     
/*  394 */     if (conn == null) {
/*  395 */       conn = mbox.getOperationConnection();
/*      */     } else {
/*  397 */       Db.registerDatabaseInterest(conn, mbox);
/*      */     }
/*      */     try
/*      */     {
/*  401 */       if (Db.supports(Db.Capability.DISABLE_CONSTRAINT_CHECK)) {
/*  402 */         conn.disableForeignKeyConstraints();
/*      */       }
/*      */       
/*      */ 
/*  406 */       ArrayList<String> tables = new ArrayList();
/*  407 */       tables.addAll(sTables);
/*  408 */       for (DbTableCallback callback : callbacks) {
/*  409 */         tables.addAll(callback.getTableNames());
/*      */       }
/*  411 */       Collections.reverse(tables);
/*      */       
/*  413 */       for (String tableName : tables)
/*  414 */         if (tableName != null)
/*      */         {
/*      */ 
/*      */ 
/*  418 */           PreparedStatement stmt = null;
/*      */           try {
/*  420 */             stmt = conn.prepareStatement("DELETE FROM " + qualifyTableName(mbox, tableName) + (DebugConfig.disableMailboxGroups ? "" : new StringBuilder().append(" WHERE mailbox_id = ").append(mailboxId).toString()));
/*      */             
/*  422 */             stmt.executeUpdate();
/*      */           } finally {
/*  424 */             DbPool.closeStatement(stmt);
/*      */           }
/*      */         }
/*      */       return;
/*  428 */     } catch (SQLException e) { throw ServiceException.FAILURE("dropMailboxFromGroup(" + mailboxId + ")", e);
/*      */     } finally {
/*      */       try {
/*  431 */         if (Db.supports(Db.Capability.DISABLE_CONSTRAINT_CHECK)) {
/*  432 */           conn.enableForeignKeyConstraints();
/*      */         }
/*      */       } catch (ServiceException e) {
/*  435 */         ZimbraLog.mailbox.error("error enabling foreign key constraints during mailbox deletion", e);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   public static void clearMailboxContent(Mailbox mbox) throws ServiceException
/*      */   {
/*  442 */     clearMailboxContent(null, mbox);
/*      */   }
/*      */   
/*      */   public static void clearMailboxContent(DbPool.DbConnection conn, Mailbox mbox) throws ServiceException {
/*  446 */     dropMailboxFromGroup(conn, mbox);
/*      */   }
/*      */   
/*      */   public static void renameMailbox(Mailbox mbox, String newName) throws ServiceException {
/*  450 */     if (DebugConfig.externalMailboxDirectory) {
/*  451 */       return;
/*      */     }
/*      */     
/*  454 */     int mailboxId = mbox.getId();
/*  455 */     ZimbraLog.mailbox.info("Renaming email/comment of mailbox " + mailboxId + " to " + newName);
/*      */     
/*  457 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*      */     try
/*      */     {
/*  460 */       PreparedStatement stmt = null;
/*      */       try {
/*  462 */         stmt = conn.prepareStatement("UPDATE mailbox SET comment = ?, last_backup_at = NULL WHERE id = ?");
/*  463 */         stmt.setString(1, newName);
/*  464 */         stmt.setInt(2, mailboxId);
/*  465 */         stmt.executeUpdate();
/*      */       } finally {
/*  467 */         DbPool.closeStatement(stmt);
/*      */       }
/*      */     } catch (SQLException e) {
/*  470 */       throw ServiceException.FAILURE("renameMailbox(" + mailboxId + ")", e);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void clearMailboxContactCount(Mailbox mbox) throws ServiceException {
/*  475 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  476 */     PreparedStatement stmt = null;
/*      */     try {
/*  478 */       stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox") + " SET contact_count = NULL WHERE id = ?");
/*      */       
/*  480 */       stmt.setInt(1, mbox.getId());
/*  481 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/*  483 */       throw ServiceException.FAILURE("clearing contact count for mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  485 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void recordLastSoapAccess(Mailbox mbox) throws ServiceException {
/*  490 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  491 */     PreparedStatement stmt = null;
/*      */     try {
/*  493 */       stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox") + " SET last_soap_access = ? WHERE id = ?");
/*      */       
/*  495 */       stmt.setInt(1, (int)(mbox.getLastSoapAccessTime() / 1000L));
/*  496 */       stmt.setInt(2, mbox.getId());
/*  497 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/*  499 */       throw ServiceException.FAILURE("updating last SOAP access time for mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  501 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void updateMailboxStats(Mailbox mbox) throws ServiceException {
/*  506 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  507 */     PreparedStatement stmt = null;
/*      */     try {
/*  509 */       stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox") + " SET item_id_checkpoint = ?, contact_count = ?, change_checkpoint = ?," + "  size_checkpoint = ?, new_messages = ? WHERE id = ?");
/*      */       
/*      */ 
/*  512 */       int pos = 1;
/*  513 */       stmt.setInt(pos++, mbox.getLastItemId());
/*  514 */       stmt.setInt(pos++, mbox.getContactCount());
/*  515 */       stmt.setInt(pos++, mbox.getLastChangeID());
/*  516 */       stmt.setLong(pos++, mbox.getSize());
/*  517 */       stmt.setInt(pos++, mbox.getRecentMessageCount());
/*  518 */       stmt.setInt(pos++, mbox.getId());
/*  519 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/*  521 */       throw ServiceException.FAILURE("updating mailbox statistics for mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  523 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void startTrackingSync(Mailbox mbox) throws ServiceException {
/*  528 */     setSyncCutoff(mbox, mbox.getLastChangeID());
/*      */   }
/*      */   
/*      */   public static void setSyncCutoff(Mailbox mbox, int cutoff) throws ServiceException {
/*  532 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  533 */     PreparedStatement stmt = null;
/*      */     try {
/*  535 */       stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox") + " SET tracking_sync = ? WHERE id = ? AND tracking_sync < ?");
/*      */       
/*  537 */       stmt.setInt(1, cutoff);
/*  538 */       stmt.setInt(2, mbox.getId());
/*  539 */       stmt.setInt(3, cutoff);
/*  540 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/*  542 */       throw ServiceException.FAILURE("turning on sync tracking for mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  544 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void startTrackingImap(Mailbox mbox) throws ServiceException {
/*  549 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  550 */     PreparedStatement stmt = null;
/*      */     try {
/*  552 */       stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox") + " SET tracking_imap = 1 WHERE id = ?");
/*      */       
/*  554 */       stmt.setInt(1, mbox.getId());
/*  555 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/*  557 */       throw ServiceException.FAILURE("turning on imap tracking for mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  559 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static String getConfig(Mailbox mbox, String section) throws ServiceException {
/*  564 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  565 */     PreparedStatement stmt = null;
/*  566 */     ResultSet rs = null;
/*      */     try {
/*  568 */       stmt = conn.prepareStatement("SELECT metadata FROM " + qualifyZimbraTableName(mbox, "mailbox_metadata") + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + "section = ?");
/*      */       
/*  570 */       int pos = 1;
/*  571 */       if (!DebugConfig.disableMailboxGroups) {
/*  572 */         stmt.setInt(pos++, mbox.getId());
/*      */       }
/*  574 */       stmt.setString(pos++, section);
/*      */       
/*  576 */       rs = stmt.executeQuery();
/*  577 */       String str; if (rs.next()) {
/*  578 */         return rs.getString(1);
/*      */       }
/*  580 */       return null;
/*      */     } catch (SQLException e) {
/*  582 */       throw ServiceException.FAILURE("getting metadata section '" + section + "' in mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  584 */       DbPool.closeResults(rs);
/*  585 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void updateConfig(Mailbox mbox, String section, Metadata config) throws ServiceException {
/*  590 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  591 */     PreparedStatement stmt = null;
/*      */     try {
/*  593 */       if (config == null) {
/*  594 */         stmt = conn.prepareStatement("DELETE FROM " + qualifyZimbraTableName(mbox, "mailbox_metadata") + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + "section = ?");
/*      */         
/*  596 */         int pos = 1;
/*  597 */         if (!DebugConfig.disableMailboxGroups) {
/*  598 */           stmt.setInt(pos++, mbox.getId());
/*      */         }
/*  600 */         stmt.setString(pos++, section.toUpperCase());
/*  601 */         stmt.executeUpdate();
/*  602 */         stmt.close();
/*      */       }
/*      */       else
/*      */       {
/*      */         try {
/*  607 */           String command = Db.supports(Db.Capability.REPLACE_INTO) ? "REPLACE" : "INSERT";
/*  608 */           stmt = conn.prepareStatement(command + " INTO " + qualifyZimbraTableName(mbox, "mailbox_metadata") + " (" + (DebugConfig.disableMailboxGroups ? "" : "mailbox_id, ") + "section, metadata)" + " VALUES (" + (DebugConfig.disableMailboxGroups ? "" : "?, ") + "?, ?)");
/*      */           
/*      */ 
/*  611 */           int pos = 1;
/*  612 */           if (!DebugConfig.disableMailboxGroups) {
/*  613 */             stmt.setInt(pos++, mbox.getId());
/*      */           }
/*  615 */           stmt.setString(pos++, section);
/*  616 */           stmt.setString(pos++, config.toString());
/*  617 */           stmt.executeUpdate();
/*      */         } catch (SQLException e) {
/*  619 */           if (Db.errorMatches(e, Db.Error.DUPLICATE_ROW)) {
/*  620 */             stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox_metadata") + " SET metadata = ? WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + "section = ?");
/*      */             
/*  622 */             int pos = 1;
/*  623 */             stmt.setString(pos++, config.toString());
/*  624 */             if (!DebugConfig.disableMailboxGroups) {
/*  625 */               stmt.setInt(pos++, mbox.getId());
/*      */             }
/*  627 */             stmt.setString(pos++, section);
/*  628 */             int numRows = stmt.executeUpdate();
/*  629 */             if (numRows != 1) {
/*  630 */               String msg = String.format("Unexpected number of rows (%d) updated for section %s", new Object[] { Integer.valueOf(numRows), section });
/*  631 */               throw ServiceException.FAILURE(msg, e);
/*      */             }
/*      */           }
/*      */         }
/*      */       }
/*      */     } catch (SQLException e) {
/*  637 */       throw ServiceException.FAILURE("setting metadata section '" + section + "' in mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  639 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void deleteConfig(Mailbox mbox, String sectionPart) throws ServiceException {
/*  644 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  645 */     PreparedStatement stmt = null;
/*      */     try {
/*  647 */       stmt = conn.prepareStatement("DELETE FROM " + qualifyZimbraTableName(mbox, "mailbox_metadata") + " WHERE " + DbMailItem.IN_THIS_MAILBOX_AND + "section like ?");
/*      */       
/*  649 */       int pos = 1;
/*  650 */       if (!DebugConfig.disableMailboxGroups) {
/*  651 */         stmt.setInt(pos++, mbox.getId());
/*      */       }
/*  653 */       stmt.setString(pos++, sectionPart);
/*  654 */       stmt.executeUpdate();
/*  655 */       stmt.close();
/*      */     } catch (SQLException e) {
/*  657 */       throw ServiceException.FAILURE("delete metadata sections like '" + sectionPart + "' in mailbox " + mbox.getId(), e);
/*      */     }
/*      */     finally {
/*  660 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void updateVersion(Mailbox mbox, MailboxVersion version) throws ServiceException {
/*  665 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  666 */     PreparedStatement stmt = null;
/*      */     try {
/*  668 */       stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox") + " SET version = ?" + (DebugConfig.disableMailboxGroups ? "" : " WHERE id = ?"));
/*      */       
/*      */ 
/*  671 */       int pos = 1;
/*  672 */       stmt.setString(pos++, version == null ? null : version.toString());
/*  673 */       pos = DbMailItem.setMailboxId(stmt, mbox, pos++);
/*  674 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/*  676 */       throw ServiceException.FAILURE("setting mailbox version to '" + version + "' in mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  678 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void updateLastPurgeAt(Mailbox mbox, long lastPurgeAt) throws ServiceException {
/*  683 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  684 */     PreparedStatement stmt = null;
/*      */     try {
/*  686 */       stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox") + " SET last_purge_at = ? WHERE id = ?");
/*      */       
/*  688 */       int pos = 1;
/*  689 */       stmt.setInt(pos++, (int)(lastPurgeAt / 1000L));
/*  690 */       pos = DbMailItem.setMailboxId(stmt, mbox, pos++);
/*  691 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/*  693 */       throw ServiceException.FAILURE("setting mailbox last_purge_at to '" + (int)(lastPurgeAt / 1000L) + "' in mailbox " + mbox.getId(), e);
/*      */     } finally {
/*  695 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static void incrementItemcacheCheckpoint(Mailbox mbox) throws ServiceException {
/*  700 */     DbPool.DbConnection conn = mbox.getOperationConnection();
/*  701 */     PreparedStatement stmt = null;
/*      */     try {
/*  703 */       stmt = conn.prepareStatement("UPDATE " + qualifyZimbraTableName(mbox, "mailbox") + " SET itemcache_checkpoint = itemcache_checkpoint + 1 WHERE id = ?");
/*      */       
/*  705 */       int pos = 1;
/*  706 */       pos = DbMailItem.setMailboxId(stmt, mbox, pos++);
/*  707 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/*  709 */       throw ServiceException.FAILURE("incrementing mailbox itemcache_checkpoint", e);
/*      */     } finally {
/*  711 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static Map<String, Integer> listMailboxes(DbPool.DbConnection conn)
/*      */     throws ServiceException
/*      */   {
/*  727 */     return listMailboxes(conn, MailboxManager.getInstance());
/*      */   }
/*      */   
/*      */   public static Map<String, Integer> listMailboxes(DbPool.DbConnection conn, MailboxManager mmgr) throws ServiceException {
/*  731 */     HashMap<String, Integer> result = new HashMap();
/*  732 */     if (DebugConfig.externalMailboxDirectory) {
/*  733 */       return result;
/*      */     }
/*      */     
/*  736 */     PreparedStatement stmt = null;
/*  737 */     ResultSet rs = null;
/*      */     try {
/*  739 */       stmt = conn.prepareStatement("SELECT account_id, id FROM mailbox");
/*  740 */       rs = stmt.executeQuery();
/*  741 */       while (rs.next()) {
/*  742 */         result.put(rs.getString(1).toLowerCase(), Integer.valueOf(rs.getInt(2)));
/*      */       }
/*  744 */       return result;
/*      */     } catch (SQLException e) {
/*  746 */       throw ServiceException.FAILURE("fetching mailboxes", e);
/*      */     } finally {
/*  748 */       DbPool.closeResults(rs);
/*  749 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static int getMailboxId(DbPool.DbConnection conn, String accountId) throws ServiceException
/*      */   {
/*  755 */     if (DebugConfig.externalMailboxDirectory) {
/*  756 */       return -1;
/*      */     }
/*      */     
/*  759 */     PreparedStatement stmt = null;
/*  760 */     ResultSet rs = null;
/*      */     try {
/*  762 */       stmt = conn.prepareStatement("SELECT id FROM mailbox WHERE account_id = ?");
/*  763 */       int pos = 1;
/*  764 */       stmt.setString(pos++, accountId);
/*  765 */       rs = stmt.executeQuery();
/*  766 */       int i; if (rs.next()) {
/*  767 */         return rs.getInt(1);
/*      */       }
/*  769 */       return -1;
/*      */     } catch (SQLException e) {
/*  771 */       throw ServiceException.FAILURE("fetching mailboxId", e);
/*      */     } finally {
/*  773 */       DbPool.closeResults(rs);
/*  774 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static Map<String, Long> getMailboxSizes(DbPool.DbConnection conn, List<Integer> mailboxIds)
/*      */     throws ServiceException
/*      */   {
/*  792 */     HashMap<String, Long> sizes = new HashMap();
/*  793 */     if (DebugConfig.externalMailboxDirectory) {
/*  794 */       return sizes;
/*      */     }
/*      */     
/*  797 */     PreparedStatement stmt = null;
/*  798 */     ResultSet rs = null;
/*      */     try {
/*  800 */       if (!DebugConfig.disableMailboxGroups) {
/*  801 */         stmt = conn.prepareStatement("SELECT account_id, size_checkpoint FROM mailbox");
/*  802 */         rs = stmt.executeQuery();
/*  803 */         while (rs.next()) {
/*  804 */           sizes.put(rs.getString(1).toLowerCase(), Long.valueOf(rs.getLong(2)));
/*      */         }
/*      */       }
/*  807 */       for (Iterator i$ = mailboxIds.iterator(); i$.hasNext();) { int mailboxId = ((Integer)i$.next()).intValue();
/*      */         
/*  809 */         Db.getInstance().registerDatabaseInterest(conn, getDatabaseName(mailboxId));
/*      */         
/*  811 */         stmt = conn.prepareStatement("SELECT account_id, size_checkpoint FROM " + qualifyZimbraTableName(mailboxId, "mailbox"));
/*  812 */         rs = stmt.executeQuery();
/*  813 */         while (rs.next()) {
/*  814 */           sizes.put(rs.getString(1).toLowerCase(), Long.valueOf(rs.getLong(2)));
/*      */         }
/*  816 */         rs.close();
/*  817 */         rs = null;
/*  818 */         stmt.close();
/*  819 */         stmt = null;
/*      */         
/*      */ 
/*  822 */         conn.commit();
/*      */       }
/*      */       
/*  825 */       return sizes;
/*      */     } catch (SQLException e) {
/*  827 */       throw ServiceException.FAILURE("fetching mailboxes", e);
/*      */     } finally {
/*  829 */       DbPool.closeResults(rs);
/*  830 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static Set<Integer> listPurgePendingMailboxes(DbPool.DbConnection conn, long time)
/*      */     throws ServiceException
/*      */   {
/*  844 */     Set<Integer> result = new HashSet();
/*  845 */     if (DebugConfig.externalMailboxDirectory) {
/*  846 */       return result;
/*      */     }
/*      */     
/*  849 */     PreparedStatement stmt = null;
/*  850 */     ResultSet rs = null;
/*      */     try {
/*  852 */       stmt = conn.prepareStatement("SELECT id FROM mailbox WHERE last_purge_at < ?");
/*  853 */       int pos = 1;
/*  854 */       stmt.setInt(pos++, (int)(time / 1000L));
/*  855 */       rs = stmt.executeQuery();
/*  856 */       while (rs.next()) {
/*  857 */         result.add(Integer.valueOf(rs.getInt(1)));
/*      */       }
/*  859 */       return result;
/*      */     } catch (SQLException e) {
/*  861 */       throw ServiceException.FAILURE("fetching purge pending mailboxes", e);
/*      */     } finally {
/*  863 */       DbPool.closeResults(rs);
/*  864 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*  868 */   public static final int CHANGE_CHECKPOINT_INCREMENT = Zimbra.isAlwaysOn() ? 1 : Math.max(1, LC.zimbra_mailbox_change_checkpoint_frequency.intValue());
/*  869 */   public static final int ITEM_CHECKPOINT_INCREMENT = Zimbra.isAlwaysOn() ? 1 : 20;
/*      */   
/*      */   public static Mailbox.MailboxData getMailboxStats(DbPool.DbConnection conn, int mailboxId)
/*      */     throws ServiceException
/*      */   {
/*  874 */     PreparedStatement stmt = null;
/*  875 */     ResultSet rs = null;
/*      */     try {
/*  877 */       if (DebugConfig.disableMailboxGroups) {
/*  878 */         Db.getInstance().registerDatabaseInterest(conn, getDatabaseName(mailboxId));
/*      */       }
/*      */       
/*      */ 
/*  882 */       stmt = conn.prepareStatement("SELECT account_id," + (DebugConfig.disableMailboxGroups ? Integer.valueOf(mailboxId) : " group_id") + "," + " size_checkpoint, contact_count, item_id_checkpoint, change_checkpoint, tracking_sync," + " tracking_imap, index_volume_id, last_soap_access, new_messages, version, itemcache_checkpoint" + " FROM " + qualifyZimbraTableName(mailboxId, "mailbox") + " WHERE id = ?");
/*      */       
/*      */ 
/*      */ 
/*      */ 
/*  887 */       stmt.setInt(1, mailboxId);
/*      */       
/*  889 */       rs = stmt.executeQuery();
/*      */       
/*  891 */       if (!rs.next()) {
/*  892 */         return null;
/*      */       }
/*      */       
/*  895 */       int pos = 1;
/*  896 */       mbd = new Mailbox.MailboxData();
/*  897 */       mbd.id = mailboxId;
/*  898 */       mbd.accountId = rs.getString(pos++).toLowerCase();
/*  899 */       mbd.schemaGroupId = rs.getInt(pos++);
/*  900 */       mbd.size = rs.getLong(pos++);
/*  901 */       if (rs.wasNull()) {
/*  902 */         mbd.size = -1L;
/*      */       }
/*  904 */       mbd.contacts = rs.getInt(pos++);
/*  905 */       if (rs.wasNull()) {
/*  906 */         mbd.contacts = -1;
/*      */       }
/*  908 */       mbd.lastItemId = rs.getInt(pos++);
/*  909 */       mbd.lastChangeId = rs.getInt(pos++);
/*  910 */       mbd.trackSync = rs.getInt(pos++);
/*  911 */       mbd.trackImap = rs.getBoolean(pos++);
/*  912 */       mbd.indexVolumeId = rs.getShort(pos++);
/*  913 */       mbd.lastWriteDate = rs.getInt(pos++);
/*  914 */       mbd.recentMessages = rs.getInt(pos++);
/*  915 */       mbd.lastBackupDate = -1;
/*      */       
/*  917 */       String version = rs.getString(pos++);
/*  918 */       if (version != null) {
/*  919 */         mbd.version = MailboxVersion.parse(version);
/*      */       }
/*  921 */       mbd.itemcacheCheckpoint = rs.getInt(pos++);
/*      */       
/*      */ 
/*  924 */       mbd.lastItemId += ITEM_CHECKPOINT_INCREMENT - 1;
/*  925 */       mbd.lastChangeId += CHANGE_CHECKPOINT_INCREMENT - 1;
/*  926 */       int rounding = mbd.lastItemId % ITEM_CHECKPOINT_INCREMENT;
/*  927 */       if (rounding != ITEM_CHECKPOINT_INCREMENT - 1) {
/*  928 */         mbd.lastItemId -= rounding + 1;
/*      */       }
/*  930 */       rounding = mbd.lastChangeId % CHANGE_CHECKPOINT_INCREMENT;
/*  931 */       if (rounding != CHANGE_CHECKPOINT_INCREMENT - 1) {
/*  932 */         mbd.lastChangeId -= rounding + 1;
/*      */       }
/*      */       
/*  935 */       rs.close();
/*  936 */       rs = null;
/*  937 */       stmt.close();
/*  938 */       stmt = null;
/*      */       
/*  940 */       stmt = conn.prepareStatement("SELECT section FROM " + qualifyZimbraTableName(mailboxId, "mailbox_metadata") + (DebugConfig.disableMailboxGroups ? "" : " WHERE mailbox_id = ?"));
/*      */       
/*  942 */       if (!DebugConfig.disableMailboxGroups) {
/*  943 */         stmt.setInt(1, mailboxId);
/*      */       }
/*  945 */       rs = stmt.executeQuery();
/*      */       
/*  947 */       while (rs.next()) {
/*  948 */         if (mbd.configKeys == null) {
/*  949 */           mbd.configKeys = new HashSet();
/*      */         }
/*  951 */         mbd.configKeys.add(rs.getString(1));
/*      */       }
/*      */       
/*  954 */       return mbd;
/*      */     } catch (SQLException e) { Mailbox.MailboxData mbd;
/*  956 */       if (Db.errorMatches(e, Db.Error.NO_SUCH_TABLE)) {
/*  957 */         return null;
/*      */       }
/*  959 */       throw ServiceException.FAILURE("fetching stats on mailbox " + mailboxId, e);
/*      */     } finally {
/*  961 */       DbPool.closeResults(rs);
/*  962 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   public static int calculateMailboxGroupId(int mailboxId) {
/*  967 */     int groups = DebugConfig.numMailboxGroups;
/*      */     
/*  969 */     return (mailboxId - 1) % groups + 1;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public static String getDatabaseName(Mailbox mbox)
/*      */   {
/*  977 */     return getDatabaseName(mbox.getSchemaGroupId());
/*      */   }
/*      */   
/*      */   public static String getDatabaseName(int groupId) {
/*  981 */     return "mboxgroup" + groupId;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public static String qualifyZimbraTableName(Mailbox mbox, String tableName)
/*      */   {
/*  988 */     return DebugConfig.disableMailboxGroups ? qualifyTableName(mbox, tableName) : tableName;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public static String qualifyZimbraTableName(int mailboxId, String tableName)
/*      */   {
/*  996 */     return DebugConfig.disableMailboxGroups ? qualifyTableName(mailboxId, tableName) : tableName;
/*      */   }
/*      */   
/*      */   public static String qualifyTableName(Mailbox mbox, String tableName) {
/* 1000 */     return qualifyTableName(mbox.getSchemaGroupId(), tableName);
/*      */   }
/*      */   
/*      */   public static String qualifyTableName(int groupId, String tableName) {
/* 1004 */     return "mboxgroup" + groupId + '.' + tableName;
/*      */   }
/*      */   
/*      */   public static void removeFromDeletedAccount(DbPool.DbConnection conn, String email)
/*      */     throws ServiceException
/*      */   {
/* 1010 */     PreparedStatement stmt = null;
/*      */     try
/*      */     {
/* 1013 */       stmt = conn.prepareStatement("DELETE FROM deleted_account WHERE email = ?");
/* 1014 */       stmt.setString(1, email.toLowerCase());
/* 1015 */       stmt.executeUpdate();
/*      */     } catch (SQLException e) {
/* 1017 */       throw ServiceException.FAILURE("deleting row for " + email + " from deleted_account table", e);
/*      */     } finally {
/* 1019 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */   private static void addToDeletedAccount(DbPool.DbConnection conn, Mailbox mbox) throws ServiceException {
/* 1024 */     if (DebugConfig.externalMailboxDirectory) {
/* 1025 */       return;
/*      */     }
/*      */     
/*      */ 
/*      */ 
/* 1030 */     String email = null;
/* 1031 */     PreparedStatement stmt = null;
/* 1032 */     ResultSet rs = null;
/*      */     try {
/* 1034 */       stmt = conn.prepareStatement("SELECT comment FROM mailbox WHERE id = ?");
/* 1035 */       stmt.setInt(1, mbox.getId());
/* 1036 */       rs = stmt.executeQuery();
/* 1037 */       if (rs.next()) {
/* 1038 */         email = rs.getString(1);
/*      */       } else {
/* 1040 */         throw ServiceException.FAILURE("no email address found for mailbox " + mbox.getId(), null);
/*      */       }
/*      */     } catch (SQLException e) {
/* 1043 */       throw ServiceException.FAILURE("getting email address for mailbox " + mbox.getId(), e);
/*      */     } finally {
/* 1045 */       DbPool.closeResults(rs);
/* 1046 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */     
/* 1049 */     boolean supportsReplaceInto = Db.supports(Db.Capability.REPLACE_INTO);
/* 1050 */     if (!supportsReplaceInto) {
/* 1051 */       removeFromDeletedAccount(conn, email);
/*      */     }
/*      */     
/*      */     try
/*      */     {
/* 1056 */       String command = supportsReplaceInto ? "REPLACE" : "INSERT";
/* 1057 */       stmt = conn.prepareStatement(command + " INTO deleted_account (email, account_id, mailbox_id, deleted_at) " + "SELECT ?, account_id, id, ? FROM mailbox WHERE id = ?");
/*      */       
/*      */ 
/* 1060 */       stmt.setString(1, email.toLowerCase());
/* 1061 */       stmt.setInt(2, (int)(System.currentTimeMillis() / 1000L));
/* 1062 */       stmt.setInt(3, mbox.getId());
/* 1063 */       stmt.executeUpdate();
/* 1064 */       stmt.close();
/*      */     } catch (SQLException e) {
/* 1066 */       throw ServiceException.FAILURE("marking mailbox " + mbox.getId() + " as deleted", e);
/*      */     } finally {
/* 1068 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public static DeletedAccount getDeletedAccount(DbPool.DbConnection conn, String email)
/*      */     throws ServiceException
/*      */   {
/* 1083 */     PreparedStatement stmt = null;
/* 1084 */     ResultSet rs = null;
/*      */     try {
/* 1086 */       stmt = conn.prepareStatement("SELECT email, account_id, mailbox_id, deleted_at FROM deleted_account WHERE email = ?");
/*      */       
/*      */ 
/* 1089 */       stmt.setString(1, email.toLowerCase());
/* 1090 */       rs = stmt.executeQuery();
/* 1091 */       String emailCol; if (rs.next()) {
/* 1092 */         emailCol = rs.getString(1);
/* 1093 */         String accountId = rs.getString(2).toLowerCase();
/* 1094 */         int mailboxId = rs.getInt(3);
/* 1095 */         long deletedAt = rs.getLong(4) * 1000L;
/* 1096 */         return new DeletedAccount(emailCol, accountId, mailboxId, deletedAt);
/*      */       }
/* 1098 */       return null;
/*      */     }
/*      */     catch (SQLException e) {
/* 1101 */       throw ServiceException.FAILURE("checking if account " + email + " is deleted", e);
/*      */     } finally {
/* 1103 */       DbPool.closeResults(rs);
/* 1104 */       DbPool.closeStatement(stmt); } }
/*      */   
/*      */   public static abstract interface DbTableCallback { public abstract void create(DbPool.DbConnection paramDbConnection, int paramInt1, int paramInt2) throws ServiceException;
/*      */     
/*      */     public abstract Collection<String> getTableNames(); }
/*      */   
/*      */   public static class DeletedAccount { private final String mEmail;
/*      */     private final String mAccountId;
/*      */     private final int mMailboxId;
/*      */     private final long mDeletedAt;
/*      */     
/* 1115 */     public DeletedAccount(String email, String accountId, int mailboxId, long deletedAt) { this.mEmail = email;
/* 1116 */       this.mAccountId = accountId;
/* 1117 */       this.mMailboxId = mailboxId;
/* 1118 */       this.mDeletedAt = deletedAt;
/*      */     }
/*      */     
/*      */     public String getEmail() {
/* 1122 */       return this.mEmail;
/*      */     }
/*      */     
/*      */     public String getAccountId() {
/* 1126 */       return this.mAccountId;
/*      */     }
/*      */     
/*      */     public int getMailboxId() {
/* 1130 */       return this.mMailboxId;
/*      */     }
/*      */     
/*      */     public long getDeletedAt() {
/* 1134 */       return this.mDeletedAt;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public static void deleteMailbox(DbPool.DbConnection conn, Mailbox mbox)
/*      */     throws ServiceException
/*      */   {
/* 1144 */     addToDeletedAccount(conn, mbox);
/*      */     
/* 1146 */     PreparedStatement stmt = null;
/*      */     try {
/* 1148 */       if (DebugConfig.disableMailboxGroups)
/*      */       {
/* 1150 */         stmt = conn.prepareStatement("DELETE FROM " + qualifyTableName(mbox, "mailbox") + " WHERE id = ?");
/*      */         
/* 1152 */         stmt.setInt(1, mbox.getId());
/* 1153 */         stmt.executeUpdate();
/* 1154 */         stmt.close();
/*      */       }
/*      */       
/*      */ 
/* 1158 */       if (!DebugConfig.externalMailboxDirectory) {
/* 1159 */         stmt = conn.prepareStatement("DELETE FROM mailbox WHERE id = ?");
/* 1160 */         stmt.setInt(1, mbox.getId());
/* 1161 */         stmt.executeUpdate();
/*      */       }
/*      */     } catch (SQLException e) {
/* 1164 */       throw ServiceException.FAILURE("deleting mailbox " + mbox.getId(), e);
/*      */     } finally {
/* 1166 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */   public static Set<String> listAccountIds(DbPool.DbConnection conn)
/*      */     throws ServiceException
/*      */   {
/* 1174 */     Set<String> accountIds = new HashSet();
/* 1175 */     if (DebugConfig.externalMailboxDirectory) {
/* 1176 */       return accountIds;
/*      */     }
/*      */     
/* 1179 */     PreparedStatement stmt = null;
/* 1180 */     ResultSet rs = null;
/*      */     try {
/* 1182 */       stmt = conn.prepareStatement("SELECT account_id FROM mailbox");
/* 1183 */       rs = stmt.executeQuery();
/* 1184 */       while (rs.next()) {
/* 1185 */         accountIds.add(rs.getString(1).toLowerCase());
/*      */       }
/*      */     } catch (SQLException e) {
/* 1188 */       throw ServiceException.FAILURE("getting distinct account ids", e);
/*      */     } finally {
/* 1190 */       DbPool.closeResults(rs);
/* 1191 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */     
/* 1194 */     return accountIds;
/*      */   }
/*      */   
/*      */   public static List<Mailbox.MailboxData> getMailboxRawData(DbPool.DbConnection conn) throws ServiceException {
/* 1198 */     List<Mailbox.MailboxData> results = new ArrayList();
/* 1199 */     if (DebugConfig.externalMailboxDirectory) {
/* 1200 */       return results;
/*      */     }
/*      */     
/* 1203 */     PreparedStatement stmt = null;
/* 1204 */     ResultSet rs = null;
/*      */     try {
/* 1206 */       if (!DebugConfig.disableMailboxGroups) {
/* 1207 */         stmt = conn.prepareStatement("SELECT id, group_id, account_id, index_volume_id, item_id_checkpoint, contact_count, size_checkpoint, change_checkpoint, tracking_sync, tracking_imap, last_backup_at, last_soap_access, new_messages FROM mailbox");
/*      */         
/*      */ 
/*      */ 
/* 1211 */         rs = stmt.executeQuery();
/* 1212 */         readMailboxRawData(results, rs);
/*      */       }
/*      */       else
/*      */       {
/* 1216 */         int[] mailboxIds = MailboxManager.getInstance().getMailboxIds();
/* 1217 */         for (int mailboxId : mailboxIds) {
/* 1218 */           Db.getInstance().registerDatabaseInterest(conn, getDatabaseName(mailboxId));
/*      */           
/* 1220 */           stmt = conn.prepareStatement("SELECT id, id, account_id, index_volume_id, item_id_checkpoint, contact_count, size_checkpoint, change_checkpoint, tracking_sync, tracking_imap, -1, last_soap_access, new_messages FROM " + qualifyZimbraTableName(mailboxId, "mailbox"));
/*      */           
/*      */ 
/*      */ 
/* 1224 */           rs = stmt.executeQuery();
/* 1225 */           readMailboxRawData(results, rs);
/* 1226 */           rs.close();
/* 1227 */           rs = null;
/* 1228 */           stmt.close();
/* 1229 */           stmt = null;
/*      */           
/*      */ 
/* 1232 */           conn.commit();
/*      */         }
/*      */       }
/*      */     } catch (SQLException e) {
/* 1236 */       throw ServiceException.FAILURE("getting distinct account id's", e);
/*      */     } finally {
/* 1238 */       DbPool.closeResults(rs);
/* 1239 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */     
/* 1242 */     return results;
/*      */   }
/*      */   
/*      */   public static void optimize(DbPool.DbConnection conn, Mailbox mbox, int level) throws ServiceException {
/* 1246 */     assert (mbox.lock.isWriteLockedByCurrentThread());
/*      */     
/* 1248 */     String name = getDatabaseName(mbox);
/*      */     try
/*      */     {
/* 1251 */       Db.getInstance().optimize(conn, name, level);
/*      */     } catch (Exception e) {
/* 1253 */       throw ServiceException.FAILURE("optimizing mailbox db " + name, e);
/*      */     }
/*      */   }
/*      */   
/*      */   private static void readMailboxRawData(List<Mailbox.MailboxData> results, ResultSet rs) throws SQLException {
/* 1258 */     while (rs.next()) {
/* 1259 */       Mailbox.MailboxData data = new Mailbox.MailboxData();
/* 1260 */       int pos = 1;
/* 1261 */       data.id = rs.getInt(pos++);
/* 1262 */       data.schemaGroupId = rs.getInt(pos++);
/* 1263 */       data.accountId = rs.getString(pos++).toLowerCase();
/* 1264 */       data.indexVolumeId = rs.getShort(pos++);
/* 1265 */       data.lastItemId = rs.getInt(pos++);
/* 1266 */       data.contacts = rs.getInt(pos++);
/* 1267 */       data.size = rs.getLong(pos++);
/* 1268 */       data.lastChangeId = rs.getInt(pos++);
/* 1269 */       data.trackSync = rs.getInt(pos++);
/* 1270 */       data.trackImap = rs.getBoolean(pos++);
/* 1271 */       data.lastBackupDate = rs.getInt(pos++);
/*      */       
/* 1273 */       data.lastWriteDate = rs.getInt(pos++);
/* 1274 */       data.recentMessages = rs.getInt(pos++);
/* 1275 */       results.add(data);
/*      */     }
/*      */   }
/*      */   
/*      */   public static Set<Integer> getMboxGroupIds(DbPool.DbConnection conn) throws ServiceException
/*      */   {
/* 1281 */     Set<Integer> groups = new HashSet();
/*      */     
/* 1283 */     PreparedStatement stmt = null;
/* 1284 */     ResultSet rs = null;
/*      */     try {
/* 1286 */       stmt = conn.prepareStatement("SELECT DISTINCT group_id FROM mailbox");
/* 1287 */       rs = stmt.executeQuery();
/* 1288 */       while (rs.next()) {
/* 1289 */         groups.add(Integer.valueOf(rs.getInt(1)));
/*      */       }
/*      */     } catch (SQLException e) {
/* 1292 */       throw ServiceException.FAILURE("getting distinct account ids", e);
/*      */     } finally {
/* 1294 */       DbPool.closeResults(rs);
/* 1295 */       DbPool.closeStatement(stmt);
/*      */     }
/*      */     
/* 1298 */     return groups;
/*      */   }
/*      */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/db/DbMailbox.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */